using System;
using System.Collections.Generic;
using System.IO;
using BLGenerator.BusinessLogic.FileGenerators;
using BLGenerator.BusinessLogic.ProjectSettings;
using BLGenerator.DataLayer;

namespace BLGenerator.BusinessLogic
{
    public class Project
    {
        private const string SETTING_NAME_DESTINATION_FOLDER = "Destination folder";
        private const string SETTING_NAME_NAMESPACE = "Namespace";
        private const string SETTING_NAME_CONNECTION_STRING = "Connection string";
        private const string SETTING_NAME_RESULT_CONNECTION_STRING = "Result connection string";

        #region Private fields

        private IOModuleFactory.IOModuleType _ioModuleType = IOModuleFactory.IOModuleType.XMLIOModule;
        private bool _isModified = true;
        private readonly ProjectSetting[] _settings;
        private readonly Dictionary<string, object> _settingValues;
        private readonly EntityCollection _entityCollection;

        #endregion

        #region Settings properties

        public string DestinationFolder
        {
            get { return (string)_settingValues[SETTING_NAME_DESTINATION_FOLDER]; }
        }

        public string Namespace
        {
            get
            {
                return (string)_settingValues[SETTING_NAME_NAMESPACE];
            }
        }

        public string ResultConnectionString
        {
            get
            {
                if (_settingValues[SETTING_NAME_NAMESPACE] == null) return "BusinessLogic";
                else return (string)_settingValues[SETTING_NAME_RESULT_CONNECTION_STRING];
            }
        }
        #endregion

        #region Properties

        public bool IsModified
        {
            get { return _isModified; }
            set
            {
                _isModified = value;
                OnIsModifiedChanged();
            }
        }
        public ProjectSetting[] Settings { get { return _settings; } }
        public Dictionary<string, object> SettingValues { get { return _settingValues; } }
        public EntityCollection EntityCollection { get { return _entityCollection; } }

        #endregion

        public Project()
        {
            IsModified = false;
            _settings = new ProjectSetting[]
                {
                    new StringProjectSetting(SETTING_NAME_DESTINATION_FOLDER),
                    new StringProjectSetting(SETTING_NAME_NAMESPACE),
                    new StringProjectSetting(SETTING_NAME_CONNECTION_STRING),
                    new StringProjectSetting(SETTING_NAME_RESULT_CONNECTION_STRING)
                };
            _settingValues = new Dictionary<string, object>(_settings.Length);
            foreach (ProjectSetting setting in _settings)
                _settingValues[setting.Name] = setting.DefaultValue;
            _entityCollection = new EntityCollection();
        }

        #region Helper methods

        public void OpenProject(string filename)
        {
            IOModuleFactory.CreateIOModule(_ioModuleType, filename, IOModuleFactory.FileOpenType.Read).OpenProject(this);
            IsModified = false;
            OnEntityCollectionChanged();
        }

        public void SaveProject(string filename)
        {
            IOModuleFactory.CreateIOModule(_ioModuleType, filename, IOModuleFactory.FileOpenType.Write).SaveProject(this);
            IsModified = false;
        }

        public void GenerateFiles()
        {
            foreach (Entity entity in _entityCollection)
            {
                if (!entity.IsGenerated) continue;

                string dirName1 = DestinationFolder + @"\Entities\";
                DirectoryInfo dirInfo1 = new DirectoryInfo(dirName1);
                if (!dirInfo1.Exists) dirInfo1.Create();
                EntityFileGenerator.Generate(entity, dirName1 + entity.EntityName + ".cs");

                string dirName2 = DestinationFolder + @"\Collections\";
                DirectoryInfo dirInfo2 = new DirectoryInfo(dirName2);
                if (!dirInfo2.Exists) dirInfo2.Create();
                EntityCollectionFileGenerator.Generate(entity, dirName2 + entity.EntityName + "Collection.cs");
            }

            string dirName3 = DestinationFolder;
            DirectoryInfo dirInfo3 = new DirectoryInfo(dirName3);
            if (!dirInfo3.Exists) dirInfo3.Create();
            DBConnectionFileGenerator.Generate(dirInfo3 + @"\DBConnection.cs", this);
        }

        #endregion

        public Report RefreshCatalog()
        {
            Report report = SQLDataLayer.RefreshEntityCollection((string) _settingValues["Connection string"], this);
            IsModified = true;
            OnEntityCollectionChanged();
            return report;
        }

        #region Events

        public event EventHandler EntityCollectionChanged;
        public event EventHandler IsModifiedChanged;

        protected virtual void OnEntityCollectionChanged()
        {
            if (EntityCollectionChanged != null)
                EntityCollectionChanged.Invoke(this, EventArgs.Empty);
        }

        protected virtual void OnIsModifiedChanged()
        {
            if (IsModifiedChanged != null)
                IsModifiedChanged.Invoke(this, EventArgs.Empty);
        }

        #endregion
    }
}